﻿using NHibernate;
using ORM.NHibernateDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ORM.NHibernateDemo.DAL.Impl
{
    public class PersonImpl : IPerson, IDisposable
    {
        private bool disposedValue;

        public PersonImpl(ISessionFactory factory)
        {
            Factory = factory;
        }

        private ISessionFactory Factory { get; set; }

        public bool Delete(Person p)
        {
            if (Factory == null)
                return false;
            var ret = false;
            using (var session = Factory.OpenSession())
            {
                var tran = session.BeginTransaction();
                try
                {
                    session.Delete(p);
                    session.Flush();
                    tran.Commit();
                    session.Clear();
                    ret = true;
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
            return ret;
        }

        public bool Insert(Person p)
        {
            if (Factory == null)
                return false;
            var ret = false;
            using (var session = Factory.OpenSession())
            {
                var tran = session.BeginTransaction();
                try
                {
                    session.Save(p);
                    session.Flush();
                    tran.Commit();
                    session.Clear();
                    ret = true;
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
            return ret;
        }

        public bool Query(Predicate<Person> pred, out IList<Person> ps)
        {
            ps = null;
            if (Factory == null)
                return false;
            var ret = false;
            using (var session = Factory.OpenSession())
            {
                var tran = session.BeginTransaction();
                try
                {
                    //TODO:query
                    var res = session.Query<Person>();
                    if(pred!=null)
                        res =res.Where(p => pred(p));
                    var ps2 = new List<Person>();
                    res.ToList()
                        .ForEach(p => ps2.Add(p));
                    ps = ps2;
                    tran.Commit();
                    session.Clear();
                    ret = true;
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
            return ret;
        }

        public bool Query(Predicate<Person> pred, out int count)
        {
            count = -1;
            if (Factory == null)
                return false;
            var ret = false;
            using (var session = Factory.OpenSession())
            {
                var tran = session.BeginTransaction();
                try
                {
                    //TODO:query
                    var res = session.Query<Person>();
                    if (pred != null)
                        res = res.Where(p => pred(p));
                    count = res.Count();
                    tran.Commit();
                    session.Clear();
                    ret = true;
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
            return ret;
        }

        public bool Update(Person p)
        {
            if (Factory == null)
                return false;
            var ret = false;
            using (var session = Factory.OpenSession())
            {
                var tran = session.BeginTransaction();
                try
                {
                    session.Update(p);
                    session.Flush();
                    tran.Commit();
                    session.Clear();
                    ret = true;
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                }
            }
            return ret;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                    if (Factory != null)
                    {
                        Factory.Close();
                        Factory.Dispose();
                    }
                }

                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
                // TODO: 将大型字段设置为 null
                disposedValue = true;
            }
        }

        // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        // ~PersonImpl()
        // {
        //     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
        //     Dispose(disposing: false);
        // }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }
}